/* 
 * File:   Player.h
 * Author: mauro
 *
 * Created on 12 de octubre de 2014, 15:49
 */

#ifndef PLAYER_H
#define	PLAYER_H

#include <stdbool.h>
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <JSON/json.hh>

#include "../Define/Structs.h"
#include "ServerSocket.h"
#include "Character.h"
#include "WorldElement.h"
#include "../Controller/BlockingQueueObject.h"
#include "../Controller/BlockingQueueEvent.h"
#include "../Controller/SBSLog.h"
#include "Circle.h"
#include "SnowBall.h"
using namespace std;

#define ERROR -1

class Player : public WorldElement{
private:
    SBSLog* myLogFile;

    int socket;
    bool init; //flag para controlar el estado del jugador.
    bool crashed; //flag para saber si crasheo o se desconecto
    BlockingQueueEvent events; //RCV
    ServerSocket server;
    std::thread threadRecv;
    std::thread threadSend;
    std::thread threadPulse;
    BlockingQueueObject objects; //SND
    bool equals;
    std::mutex mtx;
    std::mutex ptx;
    std::mutex rtx;
    bool flagHasBody;
    
    bool trapped;
    
//    bool semaforo;
    Character* character;
    int number;
    string name;
    string fileName;

    float posIniX;
    float posIniY;
    
    void updatePosition();
    void updateRotation();

public:
    bool alive;
    Player(int id);
    Player(ServerSocket &server, int socket, ObjFactory *objFactory, int number, float posX, float posY, string namePlayer);
    virtual ~Player();
//    void commuQueue(int i, struct Event &e);
//    void commuQueueR(int i, struct ObjectInit &e);
    //getters
    int getSocket();
    int getState();
    float getPosX();
    float getPosY();
    int getPixelsX();
    int getPixelsY();
    struct Event popEvent(); //solo un evento (#refactor por el tipo de evento)
    string getName ();
    int getCharacterId();
    int getUbicDyn();
    struct ObjectInit getData();
    void sendLevelFinished(struct ObjectInit myObj);
    b2Body* getBody();  
    int getScore();
    int getLifes();
    bool tryPop(struct Event &e);
//    struct Event tryPop(bool r);
    
    //setters
    void pushEvent(struct Event event); //guardo un nuevo evento del jugador.
    void setInit(bool stat);
    void pushObjects(struct ObjectInit buffer);//hay que agregar otro para enviar todos los elementos del mapa que se modificaron.
    struct ObjectInit popObjects();
    void setCrash(bool stat);
    void setUbicDyn(int i);
    void setTrapped();
    
    void reviveCharacter(ObjFactory *objFactory);

    bool isInit();
    bool isWatching();
    bool hasCrashed();
    bool hasBody();
    void setHasBody(bool b);
    
    void stopWalking();
    void stopKneeling();

    void keepJumping();
    void keepKneeling();
    void keepFallingDown();
    void keepWalking();
    void jumpingRight();
    void jumpingLeft();
    void fallLeft();
    void fallRight();

    bool isWalkingRight();
    bool isWalkingLeft();

    void checkFallingDown();
    void walkLeft();
    void walkRight();
    void kneel();
    void wait();
    void jump();

    bool emptyEvent();
    
    void communicationRecv(); //recibe todos los evento del cliente y los guarda en una cola.
    void communicationSend();
    void sendPulse();
    //int commuClient(int i, void* e, int len);
    void runThreadRecv();
    void runThreadSend();
    void runThreadPulse();
    
    bool saveGame();
    
    void checkChanges();
    void updateData();
    void updateEvent(struct Event e);
    bool getAreEquals();
    //SHOOT
    //-1 : disparo a izquierda
    // 1: disparo a derecha
    SnowBall* shoot();
    
    bool isInContactBonus();
    bool isInContactEnemy();
    bool isInContactSnowBallEnemy();
    bool isInContactCrazyBall();

    void restartPlayer();
    bool isAlive();
    void kill();
    void changeToPosInitial();
};

#endif	/* PLAYER_H */

